import java.awt.Desktop;
import java.io.FileOutputStream;
import java.util.Date;

import com.itextpdf.text.Anchor;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chapter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Section;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class PdfGenerator {
	
	private static Font titleFont = new Font(Font.FontFamily.HELVETICA, 18, Font.BOLD);
	private static Font authorFont = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD);
	
	public static void generate(Song s) {
		String tempDir = System.getProperty("java.io.tmpdir");
		String tempPath = tempDir + System.getProperty("file.separator") + s.getTitle() + ".pdf";
		try {
			Document document = new Document();
			PdfWriter.getInstance(document, new FileOutputStream(tempPath));
			document.open();
			
			document.setPageSize(PageSize.LETTER);
			document.addTitle(s.getTitle());
			document.addSubject("Programatically generated by Kutafuta");
			document.addAuthor(System.getProperty("user.name"));
			document.addCreator("Created on " + new Date() + " by Kutafuta");			
			
			Paragraph title = new Paragraph(s.getTitle(), titleFont);
			Paragraph author = new Paragraph(s.getAuthor(), authorFont);
			title.setAlignment(Element.ALIGN_CENTER);
			author.setAlignment(Element.ALIGN_CENTER);
			document.add(title);
			document.add(author);
			
			addLyrics(document, s.getLyrics());			
			
			document.close();
			System.out.println("Saved to: " + tempPath);
			Desktop dt = Desktop.getDesktop();
		    dt.open(new java.io.File(tempPath));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void addLyrics(Document document, String lyrics) {
		String lines[] = lyrics.split("\n");
		System.out.println("Lines in lyrics: " + lines.length);
		SongParagraph sp = new SongParagraph(getFullSection(null));
		boolean alreadyAdded = false;
		for (String line : lines) {
			line = line.replace("||", ""); //don't print double bars
			if (line.startsWith("[")) { //section
				String sec = line.substring(1, line.indexOf(']'));
				sp = new SongParagraph(getFullSection(sec));
				alreadyAdded = false;
			} else if (line.startsWith(".")) { //Chords
				sp.addChords(line.substring(1));
				alreadyAdded = false;
			} else if (line.startsWith(" ")) { //Lyrics
				sp.addLyrics(line.substring(1));
				alreadyAdded = false;
			} else if (line.isEmpty() && !alreadyAdded) { //add paragraph
				try {
					System.out.println("Adding song paragraph");
					document.add(sp.getParagraph());
					alreadyAdded = true;
				} catch (DocumentException e) {
					System.out.println("Could not add song paragraph!\n" + e.getMessage());
				}
			}
		}
		if (!alreadyAdded) {
			try {
				System.out.println("Adding song paragraph");
				document.add(sp.getParagraph());
				alreadyAdded = true;
			} catch (DocumentException e) {
				System.out.println("Could not add song paragraph!\n" + e.getMessage());
			}
		}
	}
	
	/**
	 * Converts section shorthand to full section name<br>
	 * See <a href="http://www.opensong.org/d/manual/getting_started">OpenSong Format</a>
	 * @param sec - the section string: V1, C, P, etc
	 * @return fully named section as a string
	 */
	private static String getFullSection(String sec) {
		if (sec == null || sec.equals(""))
			return "Section";
		
		sec = sec.toUpperCase(); //easy comparisons
		
		if (sec.startsWith("I"))
			return "Intro";
		else if (sec.startsWith("V"))
			return (sec.length() > 1) ? "Verse "+sec.charAt(1) : "Verse";
		else if (sec.startsWith("C"))
			return (sec.length() > 1) ? "Chorus "+sec.charAt(1) : "Chorus";
		else if (sec.startsWith("B"))
			return (sec.length() > 1) ? "Bridge "+sec.charAt(1) : "Bridge";
		else if (sec.startsWith("P"))
			return (sec.length() > 1) ? "Pre-Chorus "+sec.charAt(1) : "Pre-Chorus";
		else if (sec.startsWith("T"))
			return (sec.length() > 1) ? "Tag "+sec.charAt(1) : "Tag";
		
		
		//else
			return "Section";
	}

	public static void main(String[] args) {
		
		try {
			Document document = new Document();
			PdfWriter.getInstance(document, new FileOutputStream("c:/temp/SongPdf.pdf"));
			document.open();
			document.setPageSize(PageSize.LETTER);
			addMetaData(document);
			//addTitlePage(document);
			addContent(document);
			document.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// metadata can be viewed under File -> Properties
	private static void addMetaData(Document document) {
		document.addTitle("My Generated PDF");
		document.addSubject("Programatically generate PDFs");
		document.addAuthor(System.getProperty("user.name"));
		document.addCreator("Created on " + new Date());
	}

	private static void addContent(Document document) throws DocumentException {
		
		Paragraph title = new Paragraph("How He Loves", titleFont);
		Paragraph author= new Paragraph("John Mark McMillan", authorFont);
		title.setAlignment(Element.ALIGN_CENTER);
		author.setAlignment(Element.ALIGN_CENTER);
		document.add(title);
		document.add(author);
		
		SongParagraph sp = new SongParagraph("Verse 1");
		sp.addChords("C");
		sp.addLyrics("He is jealous for me");
		sp.addChords("Am");
		sp.addLyrics("Love's like a hurricane, I am a tree");
		sp.addChords("G	                                          F");
		sp.addLyrics("Bending beneath, the weight of his wind and mercy.");		
		document.add(sp.getParagraph());
		
		sp = new SongParagraph("Verse 2");
		sp.addChords("     C");
		sp.addLyrics("When all of a sudden,");
		sp.addChords("                      Am");
		sp.addLyrics("I am unaware of these afflictions eclipsed by glory,");
		sp.addChords("      G");
		sp.addLyrics("And I realize just how beautiful You are,");
		sp.addChords("        F");
		sp.addLyrics("And how great Your affections are for me.");		
		document.add(sp.getParagraph());
		
		sp = new SongParagraph("Pre-Chorus");
		sp.addChords("C                  Am");
		sp.addLyrics("Oh, how he loves us so,");
		sp.addChords("           G");
		sp.addLyrics("Oh, how he loves us,");
		sp.addChords("            F");
		sp.addLyrics("How he loves so.");
		document.add(sp.getParagraph());
		
		sp = new SongParagraph("Instrumental");
		sp.addChords("C  Am  G  F (2x)");		
		document.add(sp.getParagraph());

	}
	
	

	private static void createTable(Section subCatPart) throws BadElementException {
		PdfPTable table = new PdfPTable(3);

		// t.setBorderColor(BaseColor.GRAY);
		// t.setPadding(4);
		// t.setSpacing(4);
		// t.setBorderWidth(1);

		PdfPCell c1 = new PdfPCell(new Phrase("Table Header 1"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

		c1 = new PdfPCell(new Phrase("Table Header 2"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);

		c1 = new PdfPCell(new Phrase("Table Header 3"));
		c1.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(c1);
		table.setHeaderRows(1);

		table.addCell("1.0");
		table.addCell("1.1");
		table.addCell("1.2");
		table.addCell("2.1");
		table.addCell("2.2");
		table.addCell("2.3");

		subCatPart.add(table);

	}

	private static void createList(Section subCatPart) {
		List list = new List(true, false, 10);
		list.add(new ListItem("First point"));
		list.add(new ListItem("Second point"));
		list.add(new ListItem("Third point"));
		subCatPart.add(list);
	}

	private static void addEmptyLine(Paragraph paragraph, int number) {
		for (int i = 0; i < number; i++) {
			paragraph.add(new Paragraph(" "));
		}
	}
} //end class


class SongParagraph {
	StringBuilder sb = new StringBuilder(1024);
	
	/**
	 * @param paragraphType - Chorus, Verse 1, Pre-Chorus, etc
	 */
	public SongParagraph(String paragraphType) {
		sb.append(paragraphType + "\n");
	}
	
	public void addChords(String s) {
		sb.append(s + "\n");
	}
	
	public void addLyrics(String s) {
		sb.append(s + "\n");
	}
	
	public Paragraph getParagraph() {
		Font textFont = new Font(Font.FontFamily.COURIER, 12, Font.NORMAL);
		Paragraph p = new Paragraph(sb.toString(), textFont);
		p.setLeading(13.0f, 0.0f);
		p.setSpacingAfter(16.0f);
		return p;
	}
}